/*
 * Copyright 2011 myTDev.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.mytdev.javafx.internal.scene.control.skin;

import com.mytdev.javafx.internal.scene.control.behavior.ImageChooserBehavior;
import com.mytdev.javafx.scene.control.ImageChooser;
import com.sun.javafx.scene.control.skin.SkinBase;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.beans.binding.DoubleBinding;
import javafx.beans.binding.ObjectBinding;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ObjectProperty;
import javafx.event.EventHandler;
import javafx.scene.control.Button;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.GridPane;

/**
 *
 * @author Yann D'Isanto
 */
public class ImageChooserCaspianSkin extends SkinBase<ImageChooser, ImageChooserBehavior> {

    private static final Logger LOG = Logger.getLogger(ImageChooser.class.getName());

    private GridPane gridPane = null;

    private final Button browseButton = new Button();

    private final ImageView imageView = new ImageView();

    private final MenuItem clearMenuItem = new MenuItem("Clear");

    private final ContextMenu contextMenu = new ContextMenu(clearMenuItem);

    public ImageChooserCaspianSkin(ImageChooser imageChooser) {
        super(imageChooser, new ImageChooserBehavior(imageChooser));
        initComponent();
    }

    private void initComponent() {
        imageView.setPreserveRatio(true);
        browseButton.setGraphic(imageView);
        imageView.fitWidthProperty().bind(getSkinnable().imageWidthProperty());
        imageView.fitHeightProperty().bind(getSkinnable().imageHeightProperty());
        imageView.imageProperty().bind(new ImageBinding(getSkinnable().selectedImageProperty(), getSkinnable().noSelectionImageProperty()));

        final SizeBinding widthBinding = new SizeBinding(
                getSkinnable().imageWidthProperty(), getSkinnable().imagePaddingProperty());
        final SizeBinding heightBinding = new SizeBinding(
                getSkinnable().imageHeightProperty(), getSkinnable().imagePaddingProperty());
        browseButton.minWidthProperty().bind(widthBinding);
        browseButton.maxWidthProperty().bind(widthBinding);
        browseButton.prefWidthProperty().bind(widthBinding);
        browseButton.minHeightProperty().bind(heightBinding);
        browseButton.maxHeightProperty().bind(heightBinding);
        browseButton.prefHeightProperty().bind(heightBinding);

        clearMenuItem.setOnAction(getBehavior().getClearEventHandler());
        browseButton.setOnAction(getBehavior().getBrowseEventHandler());
        browseButton.addEventHandler(MouseEvent.MOUSE_CLICKED,
                new EventHandler<MouseEvent>() {
                    @Override
                    public void handle(MouseEvent e) {
                        if (e.getButton() == MouseButton.SECONDARY) {
                            contextMenu.show(getSkinnable(), e.getScreenX(), e.getScreenY());
                        }
                    }
                });
        gridPane = new GridPane();
        gridPane.setHgap(3);
        gridPane.add(browseButton, 0, 0);

        // add to self
        this.getStyleClass().add(this.getClass().getSimpleName()); // always add self as style class, because CSS should relate to the skin not the control
        getChildren().add(gridPane);
    }

    private static final class SizeBinding extends DoubleBinding {

        private final DoubleProperty imageSize;

        private final IntegerProperty padding;

        public SizeBinding(DoubleProperty imageSize, IntegerProperty padding) {
            super.bind(imageSize, padding);
            this.imageSize = imageSize;
            this.padding = padding;
        }

        @Override
        protected double computeValue() {
            double value = imageSize.get() + 2 * padding.get();
            LOG.log(Level.FINE, "computing size binding: {0}", value);
            return value;
        }
    }

    private static final class ImageBinding extends ObjectBinding<Image> {

        private final ObjectProperty<Image> selectedImage;

        private final ObjectProperty<Image> noSelectionImage;

        public ImageBinding(ObjectProperty<Image> selectedImage, ObjectProperty<Image> noSelectionImage) {
            super.bind(selectedImage, noSelectionImage);
            this.selectedImage = selectedImage;
            this.noSelectionImage = noSelectionImage;
        }

        @Override
        protected Image computeValue() {
            Image image = selectedImage.get();
            return image != null ? image : noSelectionImage.get();
        }
    }
}
